package com.baturu.mybatisminus.util;

import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author huangbin
 */
public class ReflectionUtils {

    /**
     * 从DAO泛型参数提取实体类，实体类需放在第一个泛型参数
     */
    public static Class<?> extractEntityClass(Class<?> daoClass) {
        Objects.requireNonNull(daoClass);
        Type[] types = daoClass.getGenericInterfaces();
        ParameterizedType target = null;
        for (Type type : types)
            if (type instanceof ParameterizedType) {
                Type[] typeArray = ((ParameterizedType) type).getActualTypeArguments();
                if (ArrayUtils.isNotEmpty(typeArray)) {
                    Type t = typeArray[0];
                    if (t instanceof TypeVariable || t instanceof WildcardType) {
                        target = null;
                        break;
                    } else {
                        target = (ParameterizedType) type;
                        break;
                    }
                }
                break;
            }
        if (target == null) {
            throw new IllegalArgumentException("fail to extract entity class from mapper class:" + daoClass.getName());
        }
        return (Class<?>) target.getActualTypeArguments()[0];
    }

    /**
     * 从DAO泛型参数提取id类，id类需放在第二个泛型参数
     */
    public static Class<?> extractIdClass(Class<?> daoClass) {
        Objects.requireNonNull(daoClass);
        Type[] types = daoClass.getGenericInterfaces();
        ParameterizedType target = null;
        for (Type type : types)
            if (type instanceof ParameterizedType) {
                Type[] typeArray = ((ParameterizedType) type).getActualTypeArguments();
                if (ArrayUtils.isNotEmpty(typeArray)) {
                    Type t = typeArray[1];
                    if (t instanceof TypeVariable || t instanceof WildcardType) {
                        target = null;
                        break;
                    } else {
                        target = (ParameterizedType) type;
                        break;
                    }
                }
                break;
            }
        if (target == null) {
            throw new IllegalArgumentException("fail to extract id class from mapper class:" + daoClass.getName());
        }
        return (Class<?>) target.getActualTypeArguments()[1];

    }


    public static List<Field> getFieldList(Class<?> clazz) {
        if (null == clazz) {
            return null;
        }
        List<Field> fieldList = new LinkedList<>();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            /* 过滤静态属性 */
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            /* 过滤 transient关键字修饰的属性 */
            if (Modifier.isTransient(field.getModifiers())) {
                continue;
            }
            fieldList.add(field);
        }
        /* 处理父类字段 */
        Class<?> superClass = clazz.getSuperclass();
        if (superClass.equals(Object.class)) {
            return fieldList;
        }
        /* 排除重载属性 */
        return excludeOverrideSuperField(fieldList, getFieldList(superClass));
    }

    private static List<Field> excludeOverrideSuperField(List<Field> fieldList, List<Field> superFieldList) {
        // 子类属性
        Map<String, Field> fieldMap = new HashMap<>();
        for (Field field : fieldList) {
            fieldMap.put(field.getName(), field);
        }
        for (Field superField : superFieldList) {
            if (null == fieldMap.get(superField.getName())) {
                // 加入重置父类属性
                fieldList.add(superField);
            }
        }
        return fieldList;
    }
}
